這個關卡的目標是利用 unlock()
函數來解鎖 Vault
合約
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Vault {
bool public locked;
bytes32 private password;
constructor(bytes32 _password) {
locked = true;
password = _password;
}
function unlock(bytes32 _password) public {
if (password == _password) {
locked = false;
}
}
}
這個合約有兩個狀態變數:
locked
: 一個布林值,用來表示金庫是否被鎖住。password
: 一個私有的 bytes32
型態變數,作為解鎖金庫的密碼。unlock()
函數會檢查傳入的 _password
是否與存儲的 password
相同,若相同則將 locked
設為 false
,解鎖金庫。
password
password
是一個 private
變數,雖然無法直接調用合約來讀取它,但由於區塊鏈上的數據都是公開的,所以我們可以通過讀取合約的 storage 來提取這個變數的值。
在 Solidity 中,每個合約的狀態變數都存儲在以 slot 為單位的永久存儲中,每個 slot 可以存儲 32 bytes (256 bits) 的資料。這些 slot 是根據變數宣告的順序和大小來分配的。
根據合約變數的順序和大小,我們可以推斷變數會存在哪個 slot 中:
locked
是一個 bool
,佔用 1 byte,存儲在 slot 0 中。password
是一個 bytes32
,佔用完整的 32 bytes,因此會存儲在 slot 1 中。password
await web3.eth.getStorageAt(contract.address, 1)
我們在題目的主控台可以利用這個來獲取 slot 1 ,也就是 password 的直。
unlock()
函數來解鎖合約,將 locked
狀態設為 false